
#include"dx11demo.h"

	Dx11DemoBase::Dx11DemoBase() : driverType_(D3D_DRIVER_TYPE_NULL),
	featureLevel_(D3D_FEATURE_LEVEL_11_0), d3dDevice_(0), d3dContext_(0),
	swapChain_(0), backBufferTarget_(0)
	{

	}

	Dx11DemoBase::~Dx11DemoBase()
	{
		Shutdown();
	}


	bool Dx11DemoBase::LoadContent()
	{
		//可以进行重载来丰富相关功能
		return true;
	}


	void Dx11DemoBase::UnloadContent()
	{
		//可以进行重载来丰富相关功能
	}


	void Dx11DemoBase::Update(float dt)
	{
	}

	void Dx11DemoBase::Render()
	{
		if (d3dContext_ == 0)
			return;
		float clearColor[4] = { 0.5f, 0.5f, 0.25f, 1.0f };
		d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);
		swapChain_->Present(0, 0);
	}


	void Dx11DemoBase::Shutdown()
	{
		UnloadContent();
		if (backBufferTarget_) backBufferTarget_->Release();
		if (swapChain_) swapChain_->Release();
		if (d3dContext_) d3dContext_->Release();
		if (d3dDevice_) d3dDevice_->Release();
		d3dDevice_ = 0;
		d3dContext_ = 0;
		swapChain_ = 0;
		backBufferTarget_ = 0;
	}


	bool Dx11DemoBase::Initialize(HINSTANCE hInstance, HWND hwnd)
	{
		hInstance_ = hInstance;        //获得当前实例
		hwnd_ = hwnd;                  //获取当前窗口句柄

		RECT dimensions;                
		GetClientRect(hwnd, &dimensions);    //获取当前client area大小（窗口大小）

		unsigned int width = dimensions.right - dimensions.left;      
		unsigned int height = dimensions.bottom - dimensions.top;

		//设置设备类型和特征等级（feature level）
		D3D_DRIVER_TYPE driverTypes[] =                      //设备类型（以下包括硬件，软件，WARP，参考四种）
		{
		   D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP,
		   D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE
		};

		unsigned int totalDriverTypes = ARRAYSIZE(driverTypes);     //ARRAYSIZE返回数组大小

		D3D_FEATURE_LEVEL featureLevels[] =      //feature level不同的硬件支持不同
		{
		   D3D_FEATURE_LEVEL_11_0,
		   D3D_FEATURE_LEVEL_10_1,
		   D3D_FEATURE_LEVEL_10_0
		};

		unsigned int totalFeatureLevels = ARRAYSIZE(featureLevels);   //ARRAYSIZE返回数组大小

        //设备及交换链创建
		DXGI_SWAP_CHAIN_DESC swapChainDesc;       //变量类型为  交换链形容子（swap chain description）
		ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));   //用零填充该变量的所有区域
		swapChainDesc.BufferCount = 1;                       //缓冲区数（此处猜测为1，则有两个缓冲区，2有三个）
		swapChainDesc.BufferDesc.Width = width;
		swapChainDesc.BufferDesc.Height = height;            //缓冲区存储的大小（和要显示的一致）
		swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;   //缓冲区存储图像的格式()
		swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;        //刷新率，60/1表示60Hz
		swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;   //缓冲区使用
		swapChainDesc.OutputWindow = hwnd;           //窗口，就是win32要做显示的窗口句柄
		swapChainDesc.Windowed = true;               //决定保存窗口或者到全屏的变量
		swapChainDesc.SampleDesc.Count = 1;          
		swapChainDesc.SampleDesc.Quality = 0;        //sample description

		unsigned int creationFlags = 0;

#ifdef _DEBUG     //debug模式有效
		creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

		HRESULT result;
		unsigned int driver = 0;

		for (driver = 0; driver < totalDriverTypes; ++driver)  
	    //循环表示对所有类型设备都尝试创建，有一个设备存在和特征level存在，创建成功
		{
			//D3D11CreateDeviceAndSwapChain()创建交换链，设备，渲染context
			result = D3D11CreateDeviceAndSwapChain(0, driverTypes[driver], 0, creationFlags,
				featureLevels, totalFeatureLevels,
				D3D11_SDK_VERSION, &swapChainDesc, &swapChain_,
				&d3dDevice_, &featureLevel_, &d3dContext_);

			if (SUCCEEDED(result))
			{
				driverType_ = driverTypes[driver];    
				break;
			}
		}

		if (FAILED(result))
		{
			DXTRACE_MSG("创建 Direct3D 设备失败!");
			return false;
		}


		//渲染目标视图创建Render Target View Creation
		ID3D11Texture2D* backBufferTexture;

		result = swapChain_->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture);

		if (FAILED(result))
		{
			DXTRACE_MSG("获取交换链后台缓存失败！");
			return false;
		}

		//创建渲染目标视图
		result = d3dDevice_->CreateRenderTargetView(backBufferTexture, 0, &backBufferTarget_);

		if (backBufferTexture)
			backBufferTexture->Release(); //释放缓冲区指针，防止内存泄漏

		if (FAILED(result))
		{
			DXTRACE_MSG("创建渲染目标视图失败!");
			return false;
		}

		//渲染到一个固定视图
		d3dContext_->OMSetRenderTargets(1, &backBufferTarget_, 0);

		//视窗创建（定义了要显示的视窗范围）
		D3D11_VIEWPORT viewport;
		viewport.Width = static_cast<float>(width);   
		viewport.Height = static_cast<float>(height);     //高度和宽度
		viewport.MinDepth = 0.0f;            //深度范围
		viewport.MaxDepth = 1.0f;
		viewport.TopLeftX = 0.0f;            //视窗的顶部左坐标
		viewport.TopLeftY = 0.0f;

		d3dContext_->RSSetViewports(1, &viewport);      //设置到视窗范围

		return LoadContent();
	}




